<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * 作用域：
    *   变量的生效范围 全局作用域 > 函数作用域 > 块级作用域
    *
    *   变量是怎么声明的
    *   let 声明变量 拥有块级作用域
    *       优点
    *           1.声明前不能使用，保证代码执行顺序
    *           2.在声明变量的时候，在let之前有一个暂时性死区，不允许访问和调用
    *
    *           console.log(a)
                let a //任何在这行之前的a的操作都会被报错
    *
    *           3.不允许重复声明，一旦声明就会报错
    *
    *   var 声明变量 被淘汰掉了 拥有函数作用域 可以突破块级作用域但不能突破函数作用域
    *       缺点：
    *           1.变量提升：变量声明的时候，提升到了当前作用域最开始的位置
    *               声明变量可以在使用变量之后，不符合预期
    *           什么叫变量提升：
    *               代码执行的时候分为两个阶段：
    *               1.预编译阶段
    *                   识别代码是否被声明了，不会执行代码
    *               2.执行阶段
    *
    *console.log(a)

    var a = 3 //此处分为两步代码 var a ; a = 3
    //此时会打印出undefined，因为var 会变量提升 就相当于只是把 var a 提升到了console.log(a)前面
    //而只是声明并未赋值 因为 a = 3 还在后面读取不到 所以会打印undefined
    *
    *           2.可以重复声明，会引起歧义
    *           var a
    *           var a
    *           var a
    *
    *           3.function 其实也是变量声明
    *           如：
    *           foo()//会报错
    *           var foo = function(){//函数表达式也会引起误会
    *               console.log(1)
    *           }
    *
    *
    *   const 声明常量(后续进行赋值操作就会报错) 不允许修改 修改就会报错 保证安全 拥有块级作用域
    *   常量名全部大写
    *   const STR = "704322723"  //密钥
    *   一定要在声明常量的时候就设置初始值，因为后续不能修改值
    *   const OBJ = {}
    *   obj = {}//是错误的，常量一旦声明就不允许修改
    *
    *   const OBJ = {
    *       a:"zst"
    *   }
    *
    *   OBJ.a = "zhong"//这个不叫修改值，这个是修改属性 对象类似于一个房子 里面的属性相当于人 换了人但是房子没变
    *
    *   const NUM = 123
    *   NUM++ //会报错吗 会 因为这个是这样写的 NUM = NUM + 1 常量值不能修改 所以
    *
    *
    foo1()//会报错，var 声明的变量会变量提升，会把var foo1 提到最前面 而foo1此时是undefined 所以foo1执行就是undefined执行 就会报错
    foo2()//在代码预编译阶段 函数整体提升到最前面 所以能执行
    foo3()//在let之前有暂时性死区 所以此时并不能访问到foo3 所以读取到foo3的时候就会报错

    var foo1 = function(){//这个是函数表达式 因为有等号赋值 但只能把var声明提升 并不能把赋值也提升
        console.log("foo1")
    }
    function foo2(){//这个是函数声明 也存在变量提升 因为函数是一等公民 所以整体会提升到最前面
        console.log("foo2")
    }
    let foo3 =  function(){
        cobsole.log("foo3")
    }
    *
    *
    * */





</script>
</body>
</html>